﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TSTreeThesis.DataMgr;
using System.IO;
using TSTreeThesis.Utilities;
using MPlusTree;
using RStarTree;
using TSTree;
using TSTreeSAX;

namespace TSTreeThesis.UI
{
    public partial class LoadData : Form
    {
        private IndexMgr indexMgr;
        private DialogResult result;
        private bool isSax;
        private int min, max, length;
        private DateTime start;
        private DateTime end;
        private double[] gaussianTable;

        public LoadData()
        {
            InitializeComponent();
            indexMgr = new IndexMgr();
            result = DialogResult.Cancel;
        }

        public void setProperties(bool t, int min, int max, int length)
        {
            this.isSax = t;
            this.min = min;
            this.max = max;
            this.length = length;
        }
        public IndexMgr GetIndexMgr()
        {
            return indexMgr;
        }

        public new DialogResult ShowDialog()
        {
            base.ShowDialog();

            return result;
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                txtFileName.Text = openFileDialog.FileName;
            }
        }

        private bool isRunning = false;
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (File.Exists(txtFileName.Text))
            {
                btnClose.Enabled = false;
                btnStart.Visible = false;
                btnBrowse.Enabled = false;
                backgroundLoadData.RunWorkerAsync(txtFileName.Text);
                isRunning = true;
            }
            else
            {
                MessageBox.Show("Please choose a data file!", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void backgroundLoadData_DoWork(object sender, DoWorkEventArgs e)
        {
            //Create data object
            Invoke((MethodInvoker)delegate
            {
                listBox.Items.Add("Preparing...");
                progressBar.Value1 = 0;
            });
            string fileName = txtFileName.Text.Remove(txtFileName.Text.LastIndexOf('.')) + ".conf";
            if (File.Exists(fileName))
                File.Delete(fileName);
            BinaryWriter writer = new BinaryWriter(new FileStream(fileName, FileMode.Create));
            writer.Write(Utility.DATA_LENGHT);
            writer.Write(Utility.SLIDING_WINDOW_SIZE_ORIGINAL);
            writer.Write(Utility.COMPRESSION_RATE);
            writer.Write(Utility.PAGE_SIZE);
            writer.Close();

            FileData data = new FileData(e.Argument.ToString(), Utility.COMPRESSION_RATE);

            //Read data
            Invoke((MethodInvoker)delegate
            {
                listBox.Items.Add("Reading data...");
                progressBar.Value1 += 0;
            });

            start = DateTime.Now;

            data.readData(0, Utility.DATA_LENGHT);
            data.normalizeData();
            indexMgr.SetMeanValue(data.MEAN);
            indexMgr.SetStdValue(data.STD);

            end = DateTime.Now;

            Invoke((MethodInvoker)delegate
            {
                listBox.Items.Add("Read data completed!\t" + end.Subtract(start).TotalMilliseconds + " Milliseconds");
                progressBar.Value1 += 15;
            });

            //Encode data by PAA
            Invoke((MethodInvoker)delegate
            {
                listBox.Items.Add("Encoding data by PAA method...");
            });

            start = DateTime.Now;

            data.encodeNomalizedData(new PAATransform());

            end = DateTime.Now;

            Invoke((MethodInvoker)delegate
            {
                listBox.Items.Add("Encoding data completed!\t" + end.Subtract(start).TotalMilliseconds + " Milliseconds");
                progressBar.Value1 = 1;
                progressBar.Value1 += 5;
            });

            //Encode data by DTW
            Invoke((MethodInvoker)delegate
            {
                listBox.Items.Add("Encoding data by DTW method...");
            });

            start = DateTime.Now;

            data.encodeDTWNomalizedData(new DTWTransform());

            end = DateTime.Now;

            Invoke((MethodInvoker)delegate
            {
                listBox.Items.Add("Encoding data completed!\t" + end.Subtract(start).TotalMilliseconds + " Milliseconds");
                progressBar.Value1 = 1;
                progressBar.Value1 += 5;
            });
            // roi rac hoa
            if (isSax)
            {
                //Encode data by DTW
                Invoke((MethodInvoker)delegate
                {
                    listBox.Items.Add("Encoding data by SAX method...");
                });

                start = DateTime.Now;
                data.encodeDTWSAXNomalizedData(new SAXTransform(),max,min,length);
                end = DateTime.Now;
                Invoke((MethodInvoker)delegate
                {
                    listBox.Items.Add("Encoding data completed!\t" + end.Subtract(start).TotalMilliseconds + " Milliseconds");
                    progressBar.Value1 = 1;
                    progressBar.Value1 += 5;
                });
            }

            //Create MPTree index
            //Invoke((MethodInvoker)delegate
            //{
            //    listBox.Items.Add("Creating M+ Tree index...");
            //});
            //start = DateTime.Now;
            //MPTree<MPTreeKey> mptreeIndex = CreateMPTreeIndex(data);
            //end = DateTime.Now;

            //Invoke((MethodInvoker)delegate
            //{
            //    listBox.Items.Add("Creating M+ Tree index completed!\t" + end.Subtract(start).Milliseconds + " Milliseconds");
            //    progressBar.Value1 += 25;
            //});

            //Create RTree index
            Invoke((MethodInvoker)delegate
            {
                listBox.Items.Add("Creating R* Tree index...");
            });
            start = DateTime.Now;
            RTree rtreeIndex = CreateRTreeIndex(data);
            end = DateTime.Now;
            Invoke((MethodInvoker)delegate
            {
                listBox.Items.Add("Creating R* Tree index completed!\t" + end.Subtract(start).TotalMilliseconds + " Milliseconds");
                progressBar.Value1 += 25;
            });

            TRTree tstreeIndex = null;
            STRTree tstreeIndexSax = null;

            if (isSax == false) { 
                //Create TSTree index
                Invoke((MethodInvoker)delegate
                {
                    listBox.Items.Add("Creating TS Tree index...");
                });

                start = DateTime.Now;
                tstreeIndex = CreateTSTreeIndex(data);
                end = DateTime.Now;
                Invoke((MethodInvoker)delegate
                {
                    listBox.Items.Add("Creating TS Tree index completed!\t" + end.Subtract(start).TotalMilliseconds + " Milliseconds");
                    progressBar.Value1 += 25;
                });
            }
            else
            {
                // create gaussiantable
                gaussianTable = Utility.setGaussianTable(length);
                //Create TSTree index
                Invoke((MethodInvoker)delegate
                {
                    listBox.Items.Add("Creating TS Tree SAX index...");
                });

                start = DateTime.Now;
                tstreeIndexSax = CreateTSTreeSAXIndex(data);
                end = DateTime.Now;
                Invoke((MethodInvoker)delegate
                {
                    listBox.Items.Add("Creating TS Tree index SAX completed!\t" + end.Subtract(start).TotalMilliseconds + " Milliseconds");
                    progressBar.Value1 += 25;
                });
            }

            //Data loaded SUCCESFULLY!
            Invoke((MethodInvoker)delegate
            {
                listBox.Items.Add("Data loaded SUCCESFULLY!");
            });

            indexMgr.SetData(data);
            //indexMgr.SetMPTree(mptreeIndex);
            if (isSax == false) {
                indexMgr.SetTSTree(tstreeIndex);
            }
            else
            {
                indexMgr.SetTSTreeSax(tstreeIndexSax);
            }
            indexMgr.SetRStarTree(rtreeIndex);
            Invoke((MethodInvoker)delegate
            {
                progressBar.Value1 = 100;
            });

        }

        private void backgroundLoadData_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            result = DialogResult.OK;
            btnClose.Enabled = true;
            btnBrowse.Enabled = true;
            isRunning = false;
        }

      
        private MPTree<MPTreeKey> CreateMPTreeIndex(FileData realData)
        {
            if (realData == null) throw new ArgumentNullException("The real data is null");
            MPTree<MPTreeKey> mptree = new MPTree<MPTreeKey>(Utility.PAGE_SIZE);

            //Delete old index
            //if (File.Exists(folder + "\\mptreeindex.mptree"))
            //    File.Delete(folder + "\\mptreeindex.mptree");
            //mptree.CreateTree(folder + "\\mptreeindex.mptree", MPNode<MPTreeKey>.EvalNumEntries(MPEntry<MPTreeKey>.SizeFromKeySize(MPTreeKey.SizeFromDim(Utility.SLIDING_WINDOW_SIZE))));

            string fileName = txtFileName.Text.Remove(txtFileName.Text.LastIndexOf('.')) + ".mptree";
            if (File.Exists(fileName))
                File.Delete(fileName);
            mptree.CreateTree(fileName, MPNode<MPTreeKey>.EvalNumEntries(MPEntry<MPTreeKey>.SizeFromKeySize(MPTreeKey.SizeFromDim(Utility.SLIDING_WINDOW_SIZE))));


            MPTreeKey key;
            for (int i = 0; i < (realData.encodedDataLength - Utility.SLIDING_WINDOW_SIZE); ++i)
            {
                key = new MPTreeKey();
                key.SetNumDimension(Utility.SLIDING_WINDOW_SIZE);
                key.SetIndex(i);
                for (int j = 0; j < Utility.SLIDING_WINDOW_SIZE; ++j)
                {
                    key.SetValueAt(j, (float)realData.PAANormalizedData[i + j]);
                }

                MPEntry<MPTreeKey> entry = new MPEntry<MPTreeKey>();
                entry.SetKey(key);

                mptree.Insert(entry);

            }

            return mptree;
        }

        private RTree CreateRTreeIndex(FileData realData)
        {
            if (realData == null) throw new ArgumentNullException("The real data is null");

            //Delete old index
            //if (File.Exists(folder + "\\rtreeindex.rtree"))
            //    File.Delete(folder + "\\rtreeindex.rtree");
            //string fName = folder + "\\rtreeindex.rtree";

            string fileName = txtFileName.Text.Remove(txtFileName.Text.LastIndexOf('.')) + ".rtree";
            if (File.Exists(fileName))
                File.Delete(fileName);
            string fName = fileName;
            //int blockLength = 256;
            //int cacheSize = 128;
            int dim = Utility.SLIDING_WINDOW_SIZE;
            //rtreeIndex = new RTree(fName, Constants.BLOCKLENGTH, Constants.CACHESIZE, dim);
            RTree rtreeIndex = new RTree(fName, Utility.PAGE_SIZE, 256, dim);
            RStarTree.Data indexedKey;
            for (int i = 0; i < (realData.encodedDataLength - Utility.SLIDING_WINDOW_SIZE); ++i)
            {
                indexedKey = new RStarTree.Data(dim, i);

                for (int j = 0; j < Utility.SLIDING_WINDOW_SIZE; ++j)
                {
                    indexedKey.data[2 * j] = (float)realData.PAANormalizedData[i + j];
                    indexedKey.data[2 * j + 1] = (float)realData.PAANormalizedData[i + j];

                }

                rtreeIndex.insert(indexedKey);
            }

            rtreeIndex.delete();
            rtreeIndex.Close();

            return new RTree(fName, 256);
        }

        private TRTree CreateTSTreeIndex(FileData realData)
        {
            if (realData == null) throw new ArgumentNullException("The real data is null");

            //Delete old index
            //if (File.Exists(folder + "\\rtreeindex.rtree"))
            //    File.Delete(folder + "\\rtreeindex.rtree");
            //string fName = folder + "\\rtreeindex.rtree";

            string fileName = txtFileName.Text.Remove(txtFileName.Text.LastIndexOf('.')) + ".tstree";
            if (File.Exists(fileName))
                File.Delete(fileName);
            string fName = fileName;
            //int blockLength = 256;
            //int cacheSize = 128;
            int dim = Utility.SLIDING_WINDOW_SIZE;
            //rtreeIndex = new RTree(fName, Constants.BLOCKLENGTH, Constants.CACHESIZE, dim);
            TRTree tstreeIndex = new TRTree(fName, Utility.PAGE_SIZE, 256, dim);
            TSData indexedKey = null;
            for (int i = 0; i < (realData.encodedDataLength - Utility.SLIDING_WINDOW_SIZE); ++i)
            {
               
               indexedKey = new TSData(dim, i);
               for (int j = 0; j < Utility.SLIDING_WINDOW_SIZE; ++j)
               {
                    //mbr
                    indexedKey.data[2 * j] = (float)realData.LDTWNormalizedData[i + j];
                    indexedKey.data[2 * j + 1] = (float)realData.UDTWNormalizedData[i + j];
                    //real data
                    indexedKey.point[j] = (float)realData.PAANormalizedData[i + j];

               }
               tstreeIndex.insert(indexedKey);
            }
     
            // tstreeIndex.delete();
            // tstreeIndex.Close();

             return tstreeIndex; // new TRTree(fName, 256);
        }

        private STRTree CreateTSTreeSAXIndex(FileData realData)
        {
            if (realData == null) throw new ArgumentNullException("The real data is null");

            //Delete old index
            //if (File.Exists(folder + "\\rtreeindex.rtree"))
            //    File.Delete(folder + "\\rtreeindex.rtree");
            //string fName = folder + "\\rtreeindex.rtree";

            string fileName = txtFileName.Text.Remove(txtFileName.Text.LastIndexOf('.')) + ".tstree";
            if (File.Exists(fileName))
                File.Delete(fileName);
            string fName = fileName;
            //int blockLength = 256;
            //int cacheSize = 128;
            int dim = Utility.SLIDING_WINDOW_SIZE;
            //rtreeIndex = new RTree(fName, Constants.BLOCKLENGTH, Constants.CACHESIZE, dim);
           
                STRTree tstreeIndex = new STRTree(fName, Utility.PAGE_SIZE, 256, dim, length, gaussianTable);
                STSData indexedKey = null;
                for (int i = 0; i < (realData.encodedDataLength - Utility.SLIDING_WINDOW_SIZE); ++i)
                {

                    indexedKey = new STSData(dim, i);
         
                    for (int j = 0; j < Utility.SLIDING_WINDOW_SIZE; ++j)
                    {
            
                        //mbr
                        indexedKey.data[2 * j] = (char)realData.LDTWSAXNormalizedData[i + j];
                        indexedKey.data[2 * j + 1] = (char)realData.UDTWSAXNormalizedData[i + j];
                        //real data
                        indexedKey.point[j] = (char)realData.PAASAXNormalizedData[i + j];
                        //add float data
                        indexedKey.fdata[j] = (float)realData.PAANormalizedData[i + j];

                      //  Console.WriteLine("test data:" + indexedKey.fdata[j].ToString());
                    }

                    tstreeIndex.insert(indexedKey);
               
                }
                //tstreeIndex.delete();
                //tstreeIndex.Close();


                return tstreeIndex; // new STRTree(fName, 256);
        }


        private void LoadData_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = isRunning;
        }


    }
}
